#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/lockdep.h>
#include <trace/events/sched.h>
#include <linux/list.h>
#include <uapi/linux/magic.h>

struct thread_info *task_thread_info(struct task_struct *task)
{
    struct thread_info *ti;

    ti = &task->thread_info;

    return ti;
}

void *task_stack_page(const struct task_struct *task)
{
    return task->stack;
}

struct thread_info *current_thread_info(void)
{
    return task_thread_info(current);
}

/*
 * Return the address of the last usable long on the stack.
 *
 * When the stack grows down, this is just above the thread
 * info struct. Going any lower will corrupt the threadinfo.
 *
 * When the stack grows up, this is the highest address.
 * Beyond that position, we corrupt data on the next page.
 */
unsigned long *end_of_stack(const struct task_struct *p)
{
#ifdef CONFIG_STACK_GROWSUP
    return (unsigned long *)((unsigned long)p->stack + THREAD_SIZE) - 1;
#else
    return p->stack;
#endif
}

void set_task_stack_end_magic(struct task_struct *tsk)
{
    unsigned long *stackend;

    stackend = end_of_stack(tsk);
    *stackend = STACK_END_MAGIC; /* for overflow detection */
}
